home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / events.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  9KB  |  372 lines

  1. /*
  2.  * $Id: events.c,v 0.91 1994/02/20 00:53:24 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  * All events service routines.
  26.  *
  27.  *  The program works by wrapping fl_qread with bit_qread
  28.  *  so that some events are consumed via installed handlers before
  29.  *  ever reaching the calling routine. This allows any function to
  30.  *  implement its own specialized mouse/keyboard sequence. In addition,
  31.  *  events like REDRAW, INPUTCHANGE etc., which always demand
  32.  *  immediate response, need not be handled by any of the functions
  33.  *  that calls bit_qread.
  34.  *
  35.  */
  36.  
  37. #if !defined(lint) && defined(F_ID)
  38. char *id_evt = "$Id: events.c,v 0.91 1994/02/20 00:53:24 zhao Pre-Release $";
  39. #endif
  40.  
  41. #include "bit.h"
  42. #include "extern.h"
  43.  
  44. /*************************************************************
  45.  * GLQhandler takes (dev, val) pair, and returns 0 if the Q event
  46.  * is handled (consumed), else return the input for other handlers.
  47.  *
  48.  * Installed handler handles user events, like mouse click etc
  49.  * in a dynamically changeable way, for exampe, in main
  50.  * leftmouse advance the flist pointer while in text, it moves
  51.  * the location of text.
  52.  ***************************************************************/
  53.  
  54. #define MAXGLQH    3        /* max number of handlers */
  55.  
  56.  
  57. static GLQhandler gl_q_handler[MAXGLQH];
  58.  
  59. /*************************************************************
  60.  * Install a handler. Installing the same handler more than
  61.  * once is the same as installing once.
  62.  **************************************************************/
  63. void
  64. install_GLQ_handler(GLQhandler glh)
  65. {
  66.     GLQhandler *wmei = gl_q_handler, *wmef = wmei + MAXGLQH;
  67.  
  68.     /* search for an empty slot */
  69.     for (; wmei < wmef && *wmei && *wmei != glh; wmei++)
  70.     ;
  71.  
  72.     if (wmei == wmef)
  73.       {
  74.       Bark("GLQhandler", "Can't install -- out of bounds");
  75.       return;
  76.       }
  77.     *wmei = glh;
  78. }
  79.  
  80. /***********************************************************
  81.  * remove a handler
  82.  ************************************************************/
  83. void
  84. remove_GLQ_handler(GLQhandler glh)
  85. {
  86.     GLQhandler *wmei = gl_q_handler, *wmef;
  87.  
  88.     for (wmef = wmei + MAXGLQH; --wmef >= wmei && *wmef != glh;)
  89.     ;
  90.  
  91.     if (wmef < wmei)        /* not found */
  92.       {
  93.       M_err("GLQhandler", "Can't remove -- no existent handler");
  94.       return;
  95.       }
  96.  
  97.     /* remove it */
  98.     *wmef = 0;
  99. }
  100.  
  101. /*************************************************************
  102.  * handle events (dev, short) by calling all installed handlers
  103.  * If the event is consumed, return 0
  104.  ****************************************************************/
  105. long
  106. handle_GLQ(long dev, short val)
  107. {
  108.     long h = dev;
  109.     GLQhandler *wmei = gl_q_handler, *wmef;
  110.  
  111.     M_info("HandleGLQ", "dev=%ld val=%d", dev, val);
  112.  
  113.     if (!dev || !val)
  114.     return 0;
  115.  
  116.     wmef = wmei + MAXGLQH;
  117.  
  118.     do
  119.       {
  120.       if (*wmei)
  121.           h = (*wmei) (dev, val);
  122.       wmei++;
  123.       }
  124.     while (h == dev && wmei < wmef);
  125.  
  126.     return h;
  127. }
  128.  
  129. /*******************************************************************
  130.  * Return the number of handlers. useful for debuging
  131.  ********************************************************************/
  132. int
  133. total_GLQ_handler(void)
  134. {
  135.     GLQhandler *wmei = gl_q_handler, *wmef;
  136.     int i;
  137.  
  138.     for (i = 0, wmef = wmei + MAXGLQH; wmei < wmef; wmei++)
  139.     if (*wmei)
  140.         i++;
  141.     return i;
  142. }
  143.  
  144. /****************************************************************
  145.  * handle_const_q handles the events that are not used by user
  146.  * routines and events that need to be handled in the same way,
  147.  * in other words, other routines never see the events handled
  148.  * by handle_const_q.
  149.  *
  150.  * If the event dev is not meant for const_q, return it.
  151.  *****************************************************************/
  152. long
  153. handle_const_q(long dev, short val)
  154. {
  155.     long ret = 0;
  156.  
  157.     if (!val)
  158.     return 0;
  159. #ifdef MDEBUG
  160.     M_info("handle_const_q", "dev = %d val=%d", (int) dev, val);
  161. #endif
  162.  
  163.     switch (dev)
  164.       {
  165.       case REDRAW:
  166.       repaint(imgptr, val);
  167.       break;
  168.       case INPUTCHANGE:
  169.       if (val > 0)
  170.           set_current_window(val);
  171.       break;
  172.       case WINQUIT:
  173.       case WINSHUT:
  174.       if (val == win_id)
  175.           clean_up();
  176.       break;
  177.       case PAUSEKEY:
  178.       pausing(imgptr);
  179.       break;
  180.       case WINFREEZE:
  181.       if (val == win_id)
  182.           bit_iconify();
  183.       else
  184.           ret = dev;
  185.       break;
  186.       case REDRAWICONIC:
  187.       if (val == win_id)
  188.           bit_draw_icon(win_id);
  189.       else
  190.           ret = dev;
  191.       break;
  192.       case WINTHAW:
  193.       if (val == win_id)
  194.           bit_de_iconify();
  195.       else
  196.           ret = dev;
  197.       break;
  198.       case MKEY:
  199.       show_info_window(-1, -1, -1, -1, 1);
  200.       break;
  201.       case SKEY:
  202.       slideshow_off();
  203.       break;
  204.       default:            /* not consumed */
  205.       ret = dev;
  206.       break;
  207.       }
  208.     return ret;
  209. }
  210.  
  211. /*****************************************************************
  212.  * Global routine to handle an event. const Q is handled first,
  213.  * and then run the user defined handlers. Return input is the
  214.  * q event is un-consumed else 0.
  215.  ****************************************************************/
  216. long
  217. bit_handle_event(long dev, short val)
  218. {
  219.     long ret = 0;
  220.  
  221.     if ((ret = handle_const_q(dev, val)))
  222.       {
  223.       /* call handle_glq only if not const events */
  224.       ret = handle_GLQ(dev, val);
  225.       }
  226.     (void) fl_check_forms();
  227.     return ret;
  228. }
  229.  
  230. /********************************************************************
  231.  * Wrapper to fl_qread: unlike fl_qread, bit_qread never blocks.
  232.  *******************************************************************/
  233. long
  234. bit_qread(short *val)
  235. {
  236.     long dev;
  237.     int done = 0;
  238.  
  239.     (void) fl_check_forms();
  240.     if (!fl_qtest())
  241.       {
  242.       return 0;
  243.       }
  244.  
  245. #ifdef MDEBUG
  246.     M_debug("Bit_Qread", "Events pending");
  247. #endif
  248.  
  249.     /*
  250.      * read event Q and handle it until no events left or there is something
  251.      * we do not know how to handle
  252.      */
  253.  
  254.     do
  255.       {
  256.       dev = fl_qread(val);
  257.       done = bit_handle_event(dev, *val);
  258.       }
  259.     while (!done && fl_qtest());
  260.     return dev;
  261. }
  262.  
  263. /****************************************************************
  264.  * check if there is any q-event pending to be processed. This
  265.  * routine is called periodically to service the event Q.
  266.  ****************************************************************/
  267. void
  268. check_emergency(void)
  269. {
  270.     short val;
  271.     long dev;
  272.  
  273.     /* if there is no Q pending, return */
  274.     if (!fl_check_forms() || !fl_qtest())
  275.     return;
  276.  
  277.     /* note bit_qread remove all Q events until a unknown Q */
  278.     switch ((dev = bit_qread(&val)))
  279.       {
  280.       case ESCKEY:
  281.       if (val)
  282.           clean_up();
  283.       break;
  284.       case KEYBD:
  285.       if (val == 27)
  286.           clean_up();
  287.       break;
  288.       default:
  289.       /* eat it */
  290. #ifdef MTRACE
  291.       M_trace("Emeg: ", "dev=%ld val=%d", dev, val);
  292. #endif
  293.       break;
  294.       }
  295. }
  296.  
  297. /************************************************************
  298.  * Pause an indefinate time until pause key is pressed again
  299.  ************************************************************/
  300. void
  301. pausing(IPTR im)
  302. {
  303.     long dev;
  304.     short val;
  305.  
  306.     show_misc_info2("Paused");
  307.     fl_deactivate_all_forms();
  308.  
  309.     do
  310.       {
  311.       (void) fl_check_forms();
  312.       dev = fl_qread(&val);
  313.  
  314.       /*
  315.        * must not call bit_handle_event and its cousins, otherwise bad
  316.        * recursion
  317.        */
  318.  
  319.       if (dev == REDRAW && val)
  320.           repaint(im, val);
  321.       else if (dev == INPUTCHANGE && val)
  322.           set_current_window(val);
  323.       }
  324.     while (dev != PAUSEKEY || !val);
  325.     fl_activate_all_forms();
  326.     hide_misc_info2();
  327. }
  328.  
  329.  
  330. /***********************************************************************
  331.  * Read event queue within a time limit specified by milliseconds. Default
  332.  * returned value is def. Nagative or zero interval disables time-out.
  333.  * Originally used alarm/itimer and longjmp, but somehow, that combination
  334.  * screwed up the internal workings of FORMS. can't think of any reason why,
  335.  * but anyway, use of msleep actually simplified things a bit.
  336.  *
  337.  * Minimum allowed pause is about 20 milli-second
  338.  ************************************************************************/
  339.  
  340. long
  341. myqread(short *val, long def, long mseconds)
  342. {
  343.     long dev = def;
  344.     unsigned int delta = 18;
  345.     int nd, i;
  346.  
  347.     if (mseconds <= 0)
  348.       {
  349.       fl_check_forms();
  350.       while (!fl_qtest())
  351.           (void) fl_do_forms();
  352.  
  353.       while (!(dev = fl_qread(val)))
  354.           ;
  355.       return dev;
  356.       }
  357.  
  358.     *val = win_id;
  359.     nd = mseconds / (delta + 2);
  360.  
  361.     fl_check_forms();
  362.     for (i = (nd < 1 ? 1 : nd); --i >= 0;)
  363.       {
  364.       if (fl_qtest())
  365.           return fl_qread(val);
  366.       msleep(delta);
  367.       if ((i % 30) == 0)
  368.           fl_check_forms();
  369.       }
  370.     return def;
  371. }
  372.